package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.annotation.AutoClean;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Category;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.SetmealEnableFailedException;
import com.sky.mapper.CategoryMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealVO;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Service
public class SetmealServiceImpl implements SetmealService {
	
	private final SetmealMapper setmealMapper;
	private final SetmealDishMapper setmealDishMapper;
	private final CategoryMapper categoryMapper;
	
	private final DishMapper dishMapper;
	
	public SetmealServiceImpl(SetmealMapper setmealMapper, SetmealDishMapper setmealDishMapper, CategoryMapper categoryMapper,
	                          DishMapper dishMapper) {
		this.setmealMapper = setmealMapper;
		this.setmealDishMapper = setmealDishMapper;
		this.categoryMapper = categoryMapper;
		this.dishMapper = dishMapper;
	}
	
	@Transactional
	@Override
	@AutoClean
	public Result addSetmeal(SetmealDTO setmealDTO) {
		if (setmealDTO == null || setmealDTO.getCategoryId() == null || setmealDTO.getName() == null
				|| setmealDTO.getImage() == null || setmealDTO.getPrice() == null) {
			return Result.error(MessageConstant.INCORRECT_PARAMETERS);
		}
		Setmeal setmeal = new Setmeal();
		BeanUtils.copyProperties(setmealDTO, setmeal);
		setmealMapper.insert(setmeal);
		List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
		if (setmealDishes.isEmpty()) {
			return Result.error(MessageConstant.INCORRECT_PARAMETERS);
		}
		setmealDishes.forEach(setmealDish -> {
			setmealDish.setSetmealId(setmeal.getId());
			setmealDishMapper.insert(setmealDish);
		});
		return Result.success();
	}
	
	@Override
	public Result setmealPage(SetmealPageQueryDTO pageQueryDTO) {
		if (pageQueryDTO.getPage() == null) {
			pageQueryDTO.setPage(1);
		}
		if (pageQueryDTO.getPageSize() == null) {
			pageQueryDTO.setPageSize(5);
		}
		PageHelper.startPage(pageQueryDTO.getPage(), pageQueryDTO.getPageSize());
		List<Setmeal> setmealList = setmealMapper.getSetmealBy(pageQueryDTO.getName(), pageQueryDTO.getCategoryId(),
				pageQueryDTO.getStatus());
		Page<Setmeal> p = (Page<Setmeal>) setmealList;
		List<SetmealVO> setmealVOS = new ArrayList<>((int) p.getTotal());
		p.forEach(setmeal -> {
			SetmealVO setmealVO = new SetmealVO();
			BeanUtils.copyProperties(setmeal, setmealVO);
			setmealVO.setCategoryName(categoryMapper.getCategoryBy(null, null, setmeal.getCategoryId()).remove(0).getName());
			setmealVOS.add(setmealVO);
		});
		PageResult pageResult = new PageResult();
		pageResult.setTotal(p.getTotal());
		pageResult.setRecords(setmealVOS);
		return Result.success(pageResult);
	}
	
	/**
	 * 删除套餐的同时删除套餐与菜品的关系
	 *
	 * @param ids
	 * @return
	 */
	@Transactional
	@Override
	@AutoClean
	public Result deleteSetmeal(List<Long> ids) {
		if (ids.isEmpty()) {
			return Result.error(MessageConstant.INCORRECT_PARAMETERS);
		}
		setmealDishMapper.deleteBySetmealId(ids);
		return Result.success(setmealMapper.delete(ids));
	}
	
	@Override
	@Cacheable(cacheNames = "SetmealCache", key = "#id")
	public Result getSetmealById(Long id) {
		if (id == null) {
			return Result.error(MessageConstant.INCORRECT_PARAMETERS);
		}
		Setmeal setmeal = setmealMapper.getSetmealBy(null, null, null, id).remove(0);
		Category category = categoryMapper.getCategoryBy(null, null, setmeal.getCategoryId()).remove(0);
		SetmealVO setmealVO = new SetmealVO();
		BeanUtils.copyProperties(setmeal, setmealVO);
		setmealVO.setCategoryName(category.getName());
		return Result.success(setmealVO);
	}
	
	@Transactional
	@Override
	@AutoClean
	public Result updateSetmeal(SetmealDTO setmealDTO) {
		if (setmealDTO == null || setmealDTO.getCategoryId() == null || setmealDTO.getName() == null
				|| setmealDTO.getImage() == null || setmealDTO.getPrice() == null || setmealDTO.getId() == null) {
			return Result.error(MessageConstant.INCORRECT_PARAMETERS);
		}
		
		Setmeal setmeal = setmealMapper.getSetmealBy(null, null, null, setmealDTO.getId()).remove(0);
		if (setmeal == null) {
			return Result.error(MessageConstant.SETMEAL_NOT_FOUND);
		}
		
		List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
		if (setmealDishes.isEmpty()) {
			return Result.error(MessageConstant.INCORRECT_PARAMETERS);
		}
		setmealDishMapper.deleteBySetmealId(Collections.singletonList(setmealDTO.getId()));
		setmealDishes.forEach(setmealDish -> {
			setmealDish.setSetmealId(setmealDTO.getId());
			setmealDishMapper.insert(setmealDish);
		});
		BeanUtils.copyProperties(setmealDTO, setmeal);
		setmealMapper.updateSetmeal(setmeal);
		return Result.success();
	}
	
	@Override
	@AutoClean
	public Result banSetmeal(Integer status, Long id) {
		if (status == null || id == null) {
			return Result.error(MessageConstant.INCORRECT_PARAMETERS);
		}
		List<Long> dishIds = setmealDishMapper.getDishIdBySetmealId(id);
		dishIds.forEach(dishId -> {
			Dish dish = dishMapper.getDishBy(null, null, null, dishId).remove(0);
			if (Objects.equals(dish.getStatus(), StatusConstant.DISABLE)) {
				throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
			}
		});
		Setmeal setmeal = setmealMapper.getSetmealBy(null, null, null, id).remove(0);
		setmeal.setStatus(status);
		setmealMapper.updateSetmeal(setmeal);
		return Result.success();
	}
}
